package main

import (
	"fmt"
	"math"
)

func main() {
	toSpecific()
	typeConversions()
	typeSwitchs()
}

func typeSwitchs() {

	fmt.Println("================拿出具体类型 switch=================")
	do(21)
	do("hello")
	do(true)
}
func do(i interface{}) {
	//v := i.(type)//  Usage of .(type) is outside of the type switch MARK  不行
	switch v := i.(type) { //MARK .(type) 这个语法只能switch用
	case int:
		//MARK 这里可以安全当int用了
		fmt.Printf("Twice %v is %v\n", v, v*2)
	case string:
		fmt.Printf("%q is %v bytes long\n", v, len(v))
	default:
		fmt.Printf("I don't know about type %T!\n", v)
	}
}

func toSpecific() {
	fmt.Println("================向具体=================")
	var i interface{} = "hello" //MARK 自动向宽转型

	s := i.(string) //MARK 手动向具体转型
	fmt.Println(s)

	s, ok := i.(string)
	fmt.Println(s, ok)

	f, ok := i.(float64) //MARK 虽然不能转 但是不报错
	fmt.Println(f, ok)

	//	f = i.(float64) //MARK 报错(panic)
	//	fmt.Println(f)

	var a anInterface
	a = SS{}
	fmt.Println(a.(SS))
}

func typeConversions() {
	fmt.Println("==================类型强转=================")
	var x, y int = 3, 4
	var f float64 = math.Sqrt(float64(x*x + y*y))
	var z uint = uint(f) //MARK 基本类型这种形式来强转
	fmt.Println(x, y, z)

	a := ByteSize(34.5) //MARK 嵌入类型 也行
	fmt.Println(a)      //34.5
	//var s SS
	//fmt.Println(anInterface(SS)) //MARK type 好像不能这么转

	// string to []byte
	s1 := "hello"
	b := []byte(s1)

	// []byte to string
	s2 := string(b)
	fmt.Println(s2)
}

type ByteSize float64

const (
	_           = iota // ignore first value by assigning to blank identifier
	KB ByteSize = 1 << (10 * iota)
	MB
	GB
	TB
	PB
	EB
	ZB
	YB
)

type anInterface interface {
	a()
}
type SS struct {
}

func (s SS) a() {
	fmt.Println("sss")
}
